package anc.tankshooter.models;

import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.opengl.texture.region.ITiledTextureRegion;

import anc.tankshooter.GameActivity;
import anc.tankshooter.map.GameMap;
import anc.tankshooter.ui.ResourcesManager;

public abstract class IDymanicObject extends AnimatedSprite {

	public enum MovingDirection{UP,RIGHT,DOWN,LEFT}
	public enum EnermyAction{MOVING,FIRE}
	
	protected long[] mDurations;
	protected int[] mFrames;
	protected int mLoopCounter;
	protected Rect mRectBound;
	
	
	/**
	 * Hướng di chuyển
	 */
	protected MovingDirection mDir;
	/**
	 * Vector di chuyen
	 */
	protected float[] mMoveVector;
	/**
	 * Van toc di chuyen
	 */
	protected float mMoveSpeed;
	/**
	 * Số mạng sống
	 */
	protected int mHeart;
	/**
	 * Trạng thái cho biết đối tượng đang sống hay chết 
	 */
	protected boolean mIsDie;

	
	public IDymanicObject(float pX, float pY, ITiledTextureRegion pTiledTextureRegion) 
	{
		super(pX, pY, pTiledTextureRegion, ResourcesManager.getInstance().mVertexManager);
		
		mMoveSpeed = 4f;
		mDir=MovingDirection.RIGHT;
		mMoveVector = new float[]{mMoveSpeed, 0};
		mHeart=1;
		mIsDie=false;
		this.setCullingEnabled(true);
		this.setCurrentTileIndex(0);
		this.setZIndex(0);
		mRectBound=new Rect(getX(), getX()+getWidth(), getY(), getY()+getHeight());
	}
	
	public void setAnimation(long[]durations, int[] frame, boolean isLoop){
		this.mDurations = durations;
		mFrames = frame;
		mLoopCounter= isLoop?-1:0;
	}
	
	/**
	 * Lấy số mạng sống hiện tại.
	 */
	public int getHeart(){
		return mHeart;
	}
	public void setHeart(int heart){
		mHeart = heart;
	}
	/**
	 * Lấy hướng di chuyển hiện tại 
	 * @return
	 */
	public MovingDirection getDir(){
		return this.mDir;
	}
	
	
	public float getSpeed(){
		return this.mMoveSpeed;
	}
	
	public void setSpeed(float speed){
		this.mMoveSpeed = speed;
		switch(mDir){
		case UP:
			this.mMoveVector[0]=0; this.mMoveVector[1]=-this.mMoveSpeed;
			break;
		case RIGHT:
			this.mMoveVector[0]=this.mMoveSpeed; this.mMoveVector[1]=0;
			break;
		case DOWN:
			this.mMoveVector[0]=0; this.mMoveVector[1]=this.mMoveSpeed;
			break;
		case LEFT:
			this.mMoveVector[0]=-this.mMoveSpeed; this.mMoveVector[1]=0;
			break;
		}
	}
	
	public float getCenterX(){
		return getX()+getWidth()/2f;
	}
	
	public float getCenterY(){
		return getY()+getHeight()/2f;
	}
	
	public void setDead(boolean value){
		mIsDie = value;
	}
	
	public boolean isDead(){
		return this.mIsDie;
	}
	
	/**
	 * Di chuyển theo hướng hiện tại.
	 */
	public void move()
	{
		this.setPosition(this.mX + mMoveVector[0], this.mY + mMoveVector[1]);
	}
	public void move(float elapseSecond)
	{
		this.setPosition(this.mX + mMoveVector[0] * elapseSecond, this.mY + mMoveVector[1] * elapseSecond);
	}
	/**
	 * Set thoi gian cho moi frame
	 * @param durations
	 */
	public void setDurations(long[] durations){
		this.mDurations=durations;
	}
	/**
	 * Set mang frame nao se duoc the hien
	 * @param frames
	 */
	public void setFrames(int[] frames){
		this.mFrames=frames;
	}
	/**
	 * Set so lan lap lai. "0" neu khong lap. "< 0" neu lap vo han
	 * @param count
	 */
	public void setLoopCount(int count){
		this.mLoopCounter=count;
	}
	
	/**
	 *Bat dau vong lap
	 */
	public void start(){
		if(mLoopCounter>0)
			this.animate(mDurations, mFrames, mLoopCounter);
		else if(mLoopCounter==0)
			this.animate(mDurations, mFrames, false);
		else this.animate(mDurations, mFrames, true);
	}
	public void stop(){
		this.stopAnimation();	
	}
	
	/**
	 * Kiem tra cham bien map hay chua
	 */
	public boolean isTouchEdge()
	{
		float edgeRight = GameActivity.CAMERA_WITDH;
		float edgeBottom = GameActivity.CAMERA_HEIGHT;
		Rect bound = getBound();
		switch(mDir)
		{
			case UP:
				if(bound.mTop <= 0) return true;
				break;
			case RIGHT:
				if(bound.mRight >= edgeRight) return true;
				break;
			case DOWN:
				if(bound.mBottom >= edgeBottom) return true;
				break;
			case LEFT:
				if(bound.mLeft <= 0) return true;
				break;
		}
		return false;
	}
	
	/**
	 * Kiem tra cham bien map hay chua
	 */
	public boolean isTouchEdge(MovingDirection dir)
	{
		float edgeRight = GameActivity.CAMERA_WITDH;
		float edgeBottom = GameActivity.CAMERA_HEIGHT;
		Rect bound = getBound();
		switch(dir)
		{
			case UP:
				if(bound.mTop <= 0) return true;
				break;
			case RIGHT:
				if(bound.mRight >= edgeRight) return true;
				break;
			case DOWN:
				if(bound.mBottom >= edgeBottom) return true;
				break;
			case LEFT:
				if(bound.mLeft <= 0) return true;
				break;
		}
		return false;
	}
	
	/**
	 * Kiem tra ra ngoai map hay chua.
	 */
	public boolean isOutMap()
	{
		float edgeRight = GameActivity.CAMERA_WITDH;
		float edgeBottom = GameActivity.CAMERA_HEIGHT;
		Rect bound = getBound();
		switch(mDir)
		{
			case UP:
				if(bound.mTop < 0 - getHeight()) return true;
				break;
			case RIGHT:
				if(bound.mRight > edgeRight + getWidth()) return true;
				break;
			case DOWN:
				if(bound.mBottom > edgeBottom + getHeight()) return true;
				break;
			case LEFT:
				if(bound.mLeft < 0 - getWidth()) return true;
				break;
		}
		return false;
	}
	
	public boolean collidesWith(IDymanicObject obj){
		return getBound().collidesWith(obj.getBound());
	}

	/******************************************
	 * ABSTRACT METHOD
	 ******************************************/
	public abstract void onUpdate(GameMap map, float elapseSecond);
	
	/**
	 * Đưa đối tượng về trạng thái ban đầu.
	 * Hàm này sẽ tùy loại đối tượng mà có hành động cụ thể
	 * Các subclass phải override các hàm này
	 */
	public abstract void reset();
	
	/**
	 * Thiết lập hướng di chuyển
	 * @param dir
	 */
	public abstract void setDir(MovingDirection dir);
	
	/**
	 * Lấy vùng body của vật thể để xét va chạm.
	 * Nhớ bỏ các phần trong suốt để va chạm chính xác hơn
	 * @return
	 */
	public abstract Rect getBound();
}
